package com.gitee.farmer.im.core;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gitee.farmer.App;
import com.gitee.farmer.im.entity.FarmerMessage;
import com.gitee.farmer.im.rabbit.sender.Sender;
import com.gitee.farmer.im.service.FarmerMessageService;
import com.gitee.farmer.im.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author tech-farmer
 * @ClassName: FarmerSocket
 * @Description: (这里用一句话描述这个类的作用)
 * @date 2022/2/24 16:26
 */
@Component
@ServerEndpoint("/websocket/{userName}")
@Slf4j
public class FarmerSocket {

    private static Map<String, Session> clientMap = new ConcurrentHashMap<>();

    @OnOpen
    public void open(@PathParam("userName") String userName, Session session) {
        try {
            if(clientMap.containsKey(userName)){
                Session oldSession = clientMap.get(userName);
                if(!StringUtils.equals(session.getId(),oldSession.getId())){
                    oldSession.close();
                    clientMap.remove(userName);
                }
            }
            clientMap.put(userName, session);
            final UserService userService = App.applicationContext.getBean(UserService.class);
            final int login = userService.login(userName);
            log.info("用户【{}】建立连接成功。。。", userName);
        } catch (Exception e) {
            log.info("建立连接异常");
        }
    }

    @OnClose
    public void close(@PathParam("userName") String userName) {
        try {
            clientMap.get(userName).close();
            clientMap.remove(userName);
            final UserService userService = App.applicationContext.getBean(UserService.class);
            final int logout = userService.logout(userName);
            log.info("用户【{}】关闭连接成功。。。", userName);
        } catch (Exception e) {
            log.info("关闭连接异常");
        }
    }

    @OnMessage
    public void message(@PathParam("userName")String userName, String message,Session session) {
        try {
            JSONObject jsonTo = JSON.parseObject(message);
            final Sender bean = App.applicationContext.getBean(Sender.class);
            if(StringUtils.equalsIgnoreCase("heartbreak",jsonTo.getString("type"))){
                log.debug("接收心跳消息：{}",jsonTo);
                final UserService userService = App.applicationContext.getBean(UserService.class);
                //更新用户在线状态
                final int alive = userService.alive(userName);
                return ;
            }
            log.info("{}用户接收到消息：{}",userName,jsonTo);
            jsonTo.put("from",userName);
            final FarmerMessageService messageService = App.applicationContext.getBean(FarmerMessageService.class);
            final FarmerMessage save = messageService.save(jsonTo);
            jsonTo.put("id",save.getId());
            bean.send(jsonTo.toJSONString());
        } catch (Exception e) {
            log.info("接收消息异常",e);
        }
    }


    @OnError
    public void error(Session session, Throwable error) {
        log.error("WebSocket 异常：{}", error.getMessage());
    }

    public void receive(String payload) {
        try {
            JSONObject jsonTo = JSON.parseObject(payload);
            String type = (String) jsonTo.get("type");
            if(StringUtils.equalsIgnoreCase("heartbreak",type)){
              log.debug("发送心跳消息：{}",payload);
            }else{
                log.info("接收到消息：{}",payload);
            }
            String toUser = (String) jsonTo.get("to");
            if(StringUtils.equalsIgnoreCase("down",type)){
                if(clientMap.containsKey(toUser)){
                    clientMap.get(toUser).close();
                    clientMap.remove(toUser);
                }
            }
            if(clientMap.containsKey(toUser)){
                final Session session = clientMap.get(toUser);
                session.getAsyncRemote().sendText(payload);
            }

        } catch (IOException e) {
            log.info("强制下线失败");
        }

    }


}
